#include "stdint.h"
#include "stdio.h"
#include "n32g031.h"
#include "DevicesQueue.h"
#include "DevicesTime.h"
#include "DevicesSoftTimer.h"
#include "DevicesQueue.h"
#include "DevicesInfrared.h"



SoftTimerTypeDef g_typeSoftTimerInfraredLeftHanle = {0};
SoftTimerTypeDef g_typeSoftTimerInfraredRightHanle = {0};
SoftTimerTypeDef g_typeSoftTimerInfraredLeftFrontHanle = {0};
SoftTimerTypeDef g_typeSoftTimerInfraredRightFrontHanle = {0};


void vSoftTimerInfraredCallbackFunction(void *pvHandle)
{
#if 1
    if((uint32_t)pvHandle == (uint32_t)(&g_typeSoftTimerInfraredLeftHanle))
    {
        cInfraredSendValue(INFRARED_CHANNEL_LEFT, INFRARED_VALUE_LEFT);
        cSoftTimerReset(&g_typeSoftTimerInfraredRightHanle);
    }
    else if((uint32_t)pvHandle == (uint32_t)(&g_typeSoftTimerInfraredRightHanle))
    {
        cInfraredSendValue(INFRARED_CHANNEL_RIGHT, INFRARED_VALUE_RIGHT);
        cSoftTimerReset(&g_typeSoftTimerInfraredLeftFrontHanle);
    }
    else if((uint32_t)pvHandle == (uint32_t)(&g_typeSoftTimerInfraredLeftFrontHanle))
    {
        cInfraredSendValue(INFRARED_CHANNEL_LEFT_FRONT, INFRARED_VALUE_LEFT_FRONT);
        cSoftTimerReset(&g_typeSoftTimerInfraredRightFrontHanle);
    }
    else if((uint32_t)pvHandle == (uint32_t)(&g_typeSoftTimerInfraredRightFrontHanle))
    {
        cInfraredSendValue(INFRARED_CHANNEL_RIGHT_FRONT, INFRARED_VALUE_RIGHT_FRONT);
        cSoftTimerReset(&g_typeSoftTimerInfraredLeftHanle);
    }

#else
    switch((uint32_t)pvHandle)
    {
        case (uint32_t)(&g_typeSoftTimerInfraredLeftHanle):
            cInfraredSendValue(INFRARED_CHANNEL_LEFT, INFRARED_VALUE_LEFT);
            cSoftTimerReset(&g_typeSoftTimerInfraredRightHanle);
            break;

        case (uint32_t)(&g_typeSoftTimerInfraredRightHanle):
            cInfraredSendValue(INFRARED_CHANNEL_RIGHT, INFRARED_VALUE_RIGHT);
            cSoftTimerReset(&g_typeSoftTimerInfraredLeftFrontHanle);
            break;

        case (uint32_t)(&g_typeSoftTimerInfraredLeftFrontHanle):
            cInfraredSendValue(INFRARED_CHANNEL_LEFT_FRONT, INFRARED_VALUE_LEFT_FRONT);
            cSoftTimerReset(&g_typeSoftTimerInfraredRightFrontHanle);
            break;

        case (uint32_t)(&g_typeSoftTimerInfraredRightFrontHanle):
            cInfraredSendValue(INFRARED_CHANNEL_RIGHT_FRONT, INFRARED_VALUE_RIGHT_FRONT);
            cSoftTimerReset(&g_typeSoftTimerInfraredLeftHanle);
            break;

        default : break;
    }

#endif
}

void vInfraredInit(void)
{
    vInfraredInputInit();
    vInfraredOutputInit();

    /* 新建软件定时器 */
    cSoftTimerCreateMs(&g_typeSoftTimerInfraredLeftHanle, 25, softTimerClose, vSoftTimerInfraredCallbackFunction);
    cSoftTimerCreateMs(&g_typeSoftTimerInfraredRightHanle, 25, softTimerClose, vSoftTimerInfraredCallbackFunction);
    cSoftTimerCreateMs(&g_typeSoftTimerInfraredLeftFrontHanle, 25, softTimerClose, vSoftTimerInfraredCallbackFunction);
    cSoftTimerCreateMs(&g_typeSoftTimerInfraredRightFrontHanle, 25, softTimerClose, vSoftTimerInfraredCallbackFunction);

    /* 开启软件定时器 */
    cSoftTimerReset(&g_typeSoftTimerInfraredLeftHanle);
}

void vInfraredInputInit(void)
{
}

void vInfraredOutputInit(void)
{
    GPIO_InitType GPIO_InitStructure = {0};
    TIM_TimeBaseInitType TIM_TimeBaseStructure = {0};
    OCInitType TIM_OCInitStructure = {0};
    NVIC_InitType NVIC_InitStructure = {0};


    /* TIMx clock enable */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_TIM1, ENABLE);
    /* GPIOx clock enable */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA | RCC_APB2_PERIPH_AFIO,   ENABLE);


    GPIO_InitStruct(&GPIO_InitStructure);
    /* GPIOA Configuration:TIM3 Channel1, 2, 3 and 4 as alternate function push-pull */
    GPIO_InitStructure.Pin        = GPIO_PIN_8;
    GPIO_InitStructure.GPIO_Mode  = GPIO_MODE_AF_PP;
    GPIO_InitStructure.GPIO_Current = GPIO_DC_LOW;
    GPIO_InitStructure.GPIO_Alternate = GPIO_AF2_TIM1;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.Pin        = GPIO_PIN_9;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.Pin        = GPIO_PIN_10;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.Pin        = GPIO_PIN_11;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);


    /* 定时器1当作载波信号 */
    /* Time base configuration */
    TIM_TimeBaseStructure.Prescaler = 1 - 1;
    TIM_TimeBaseStructure.Period    = (SystemCoreClock / 38000) - 1;
    TIM_TimeBaseStructure.CntMode   = TIM_CNT_MODE_UP;
    TIM_TimeBaseStructure.ClkDiv    = 0;
    TIM_TimeBaseStructure.RepetCnt  = 0;
    TIM_InitTimeBase(TIM1, &TIM_TimeBaseStructure);

    /* PWM1 Mode configuration: Channelx */
    TIM_OCInitStructure.OcMode      = TIM_OCMODE_PWM1;
    TIM_OCInitStructure.OutputState = TIM_OUTPUT_STATE_ENABLE;
    TIM_OCInitStructure.Pulse       = TIM_TimeBaseStructure.Period / 2;
    TIM_OCInitStructure.OcPolarity  = TIM_OC_POLARITY_HIGH;
    TIM_OCInitStructure.OutputNState = TIM_OUTPUT_NSTATE_DISABLE;
    TIM_OCInitStructure.OcNPolarity  = TIM_OCN_POLARITY_HIGH;
    TIM_OCInitStructure.OcIdleState  = TIM_OC_IDLE_STATE_SET;
    TIM_OCInitStructure.OcNIdleState = TIM_OC_IDLE_STATE_RESET;
    TIM_InitOc1(TIM1, &TIM_OCInitStructure);
    TIM_InitOc2(TIM1, &TIM_OCInitStructure);
    TIM_InitOc3(TIM1, &TIM_OCInitStructure);
    TIM_InitOc4(TIM1, &TIM_OCInitStructure);

    /* TIMx enable counter */
    TIM_Enable(TIM1, ENABLE);

    /* TIM1 Main Output Enable */
    TIM_EnableCtrlPwmOutputs(TIM1, ENABLE);


    /* 定时器3当作包络信号 */
    /* TIMx clock enable */
    RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM3, ENABLE);

    /* Time base configuration */
    TIM_TimeBaseStructure.Prescaler = (SystemCoreClock / 1000000) - 1;
    TIM_TimeBaseStructure.Period    = 565 - 1;
    TIM_InitTimeBase(TIM3, &TIM_TimeBaseStructure);

    /* Enable the TIMx global Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel         = TIM3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd      = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* TIMx IT enable */
    TIM_ConfigInt(TIM3, TIM_INT_UPDATE, ENABLE);

    /* TIMx enable counter */
    TIM_Enable(TIM3, ENABLE);
}

int8_t cInfraredSendValue(uint8_t ucChannel, uint8_t ucValue)
{
    uint8_t ucMask = 0, i = 0;

    /* 起始帧头 */
    for(i = 0; i < 8; ++i)
    {
        enumQueuePushByte(&g_TypeQueueInfraredOutput, ucChannel | 0x80);
    }
    for(i = 0; i < 16; ++i)
    {
        enumQueuePushByte(&g_TypeQueueInfraredOutput, ucChannel);
    }

    /* 数据帧 4bit */
    for(ucMask = 0x08; ucMask; ucMask >>= 1)
    {
        enumQueuePushByte(&g_TypeQueueInfraredOutput, ucChannel | 0x80);
        enumQueuePushByte(&g_TypeQueueInfraredOutput, ucChannel);

        if(ucValue & ucMask)
        {
            enumQueuePushByte(&g_TypeQueueInfraredOutput, ucChannel);
            enumQueuePushByte(&g_TypeQueueInfraredOutput, ucChannel);
        }
    }

    /* 结束帧 */
    enumQueuePushByte(&g_TypeQueueInfraredOutput, ucChannel | 0x80);
    enumQueuePushByte(&g_TypeQueueInfraredOutput, ucChannel);
    enumQueuePushByte(&g_TypeQueueInfraredOutput, ucChannel);
    enumQueuePushByte(&g_TypeQueueInfraredOutput, ucChannel);

    /* 开启定时器3，以启动红外编码输出 */
    TIM_Enable(TIM3, ENABLE);

    return 0;
}
